Einführung

  • Bisher haben wir ausschließlich statische Grafiken erzeugt.
  • Forschungsergebnisse werden zunehmend nicht mehr nur in Printmedien dargestellt, sodass wir animierte und interaktive Grafiken teilen können. So kann noch mehr Information in einer einzigen “Grafik” zugänglich gemacht werden!

Foto von Jakob Owens auf Unsplash

Vorbereitung

Pakete, die wir für die Beispiele im Foliensatz benötigen:

library(ggplot2)
library(dplyr)
library(tidyr)
library(ggthemes)
library(gganimate)
library(plotly)
library(htmlwidgets)

Datensatz

gapminder <- readRDS(url("https://github.com/nickhaf/PlotWorkshop/raw/refs/heads/main/data/gapminder_dat.rds"))

Animierte Grafiken

  • Die Grundidee bei animierten Grafiken ist es, nicht einen einzigen Plot zu erstellen, sondern stattdessen sehr viele Einzelgrafiken, die dann als einzelne Bilder zu einem Film zusammengefügt werden. Das übernimmt gganimate für uns!
  • Zwei zentrale Fragen, die man sich stellen sollte, bevor man anfängt Daten zu animieren:
    - “Gewinnt der Betrachter bzw. die Betrachterin dabei zusätzliche Information?”
    - “Ist es den Aufwand wert?”

Dokumentation bzw. weiterführende Quellen:

Animierte Grafiken

Ausgangspunkt für eine animierte Grafik mit gganimate ist eine statische, mit ggplot2 erzeugte Grafik.

gapminder_line_g7 <- gapminder %>%
  filter(country %in% c("can", "fra", "deu", "ita", "jpn", "gbr", "usa"), time >=1900, time <= 2024) %>%
  drop_na(gini)

labels_g7 <- c(
  "can" = "Kanada",
  "fra" = "Frankreich",
  "deu" = "Deutschland",
  "ita" = "Italien",
  "jpn" = "Japan",
  "gbr" = "Vereinigtes Königreich",
  "usa" = "USA"
)

gapminder_line_g7$country_de <- labels_g7[gapminder_line_g7$country]
gapminder_line_g7$country_de <- factor(gapminder_line_g7$country_de,
                        levels = sort(unique(gapminder_line_g7$country_de)))

p_line_g7 <- ggplot(data = gapminder_line_g7, aes(x = time, y = gini)) +
  geom_line(aes(col = country_de)) +  
  labs(title = "Ungleichheit On the Rise", 
     subtitle = "Gini-Koeffizient in den G7-Staaten von 1900 bis 2024",
     x = "Jahr",
     y = "Gini-Koeffizient", 
     col = "G7-Staat") +
  scale_color_discrete(labels = labels_g7) +
  theme_solarized() 

p_line_g7

Animierte Grafiken

Mit transition_reveal(along = time) werden die Linien über die Zeit “enthüllt”.

p_line_g7 + 
  transition_reveal(along = time) +# Linien werden über die Zeit "enthüllt"
  ease_aes("linear")  

Noch mehr animierte Grafiken

Auch unser bubble chart lässt sich animieren. Dies ist die statische Ausgangsbasis.

options(scipen=10)

# Farben der vier Weltregionen 
tuerkis <- rgb(0,213,233, max=255)
gruen <- rgb(127,235,0, max=255)
rot <- rgb(255,88,114, max=255)
gelb <- rgb(255,231,0, max=255)

p_static <- gapminder %>%
  subset(time == 2019) %>% 
  mutate(pop = pop/1000000) %>%
  ggplot(aes(x=gini, y=hapiscore_whr)) +
  annotate("text", x=45, y=50, label="2019", size=85, colour ="grey90", family="mono", fontface=1) +
  theme_classic() + 
  geom_point(aes(fill = world_4region, size = pop), shape=21, alpha=.7) +
  scale_size(range = c(1, 30)) +
  labs(x="Gini-Index", y="Happiness Score") +
  scale_y_continuous(limits = c(15, 85), 
                     breaks = seq(20,80, by=10),
                     labels = paste0(seq(20,80, by=10), "%")) +
  scale_x_continuous(limits = c(18,75),
                     breaks = seq(20,70, by= 5)) +
  scale_fill_manual(
    values = c(tuerkis, gruen, rot, gelb),
    breaks = c("africa", "americas", "asia", "europe")) +
  theme(text = element_text(size=12),
        axis.text = element_text(size=rel(.8)),
        axis.title = element_text(size=rel(1.2)),
        panel.grid.major = element_line(colour = "azure2")) +
  labs(title="Bubble Chart im Gapminder-Look",
       subtitle="Jahr: 2023",
       x="Gini-Index",
       y="Happiness Score (WHR)",
       fill="Weltregion",
       size="Einwohnerzahl\n(in Mio.)") +
  guides(fill = guide_legend(override.aes = list(size = 5), order=1))  

p_static

Noch mehr animierte Grafiken

Nun wird für jedes Jahr ein neues Bubble chart erzeugt.

options(scipen=10)

# Farben der vier Weltregionen 
tuerkis <- rgb(0,213,233, max=255)
gruen <- rgb(127,235,0, max=255)
rot <- rgb(255,88,114, max=255)
gelb <- rgb(255,231,0, max=255)

p_static <- gapminder %>%
  subset(time >= 2005 & time <= 2023) %>% 
  mutate(pop = pop/1000000) %>%
  ggplot(aes(x=gini, y=hapiscore_whr)) +
  theme_classic() + 
  geom_point(aes(fill = world_4region, size = pop), shape=21, alpha=.7) +
  scale_size(range = c(1, 30)) +
  labs(x="Gini-Index", y="Happiness Score") +
  scale_y_continuous(limits = c(15, 85), 
                     breaks = seq(20,80, by=10),
                     labels = paste0(seq(20,80, by=10), "%")) +
  scale_x_continuous(limits = c(18,75),
                     breaks = seq(20,70, by= 5)) +
  scale_fill_manual(
    values = c(tuerkis, gruen, rot, gelb),
    breaks = c("africa", "americas", "asia", "europe")) +
  theme(text = element_text(size=12),
        axis.text = element_text(size=rel(.8)),
        axis.title = element_text(size=rel(1.2)),
        panel.grid.major = element_line(colour = "azure2")) +
  labs(title="Bubble Chart im Gapminder-Look",
       subtitle = "Jahr: {floor(frame_time)}",
       x="Gini-Index",
       y="Happiness Score (WHR)",
       fill="Weltregion",
       size="Einwohnerzahl\n(in Mio.)") +
  guides(fill = guide_legend(override.aes = list(size = 5), order=1)) 

p_static + transition_time(time) +
  ease_aes("linear")

Animierte Grafiken speichern

Die mit gganimate animierten Grafiken können mit der Funktion anim_save() als gif-Datei gespeichert werden.

p_anim <- p_static + transition_time(time) +
  ease_aes("linear") 

anim_save("bubbles.gif", animation = p_anim)

Um die Größe und Proportionen der gespeicherten Animation zu kontrollieren, kann man wie folgt vorgehen:

animate(p_anim, height = 10, width = 20, units = "cm", res = 150)
anim_save("bubbles_wide.gif")

Interaktive Grafiken

Mit dem Paket plotly lassen sich interaktive Grafiken erzeugen:

  • einzelne Fälle bzw. Gruppen von Fällen können hevorgehoben werden
  • es kann in Plots hereingezoomt werden
  • per mouse-over werden Textfelder zum jeweiligen Datenpunkt angezeigt, deren Inhalt und Aufbau sich genau definieren lässt

Interaktive Grafik mit plotly

Auch hier bildet eine statische, mit ggplot erzeugte Grafik den Ausgangspunkt.

gapminder <- readRDS(here::here("data", "gapminder_dat.rds"))

options(scipen=10)
# Farben der vier Weltregionen 
tuerkis <- rgb(0,213,233, max=255)
gruen <- rgb(127,235,0, max=255)
rot <- rgb(255,88,114, max=255)
gelb <- rgb(255,231,0, max=255)

p_bubble <- gapminder %>%
  subset(time == 2023) %>% 
  mutate(pop = pop/1000000) %>%
  ggplot(aes(x=gini, y=hapiscore_whr)) +
  annotate("text", x=45, y=50, label="2023", size=85, colour ="grey90", family="mono", fontface=1) +
  theme_classic() + 
  geom_point(aes(fill = world_4region, size = pop), shape=21, alpha=.7) +
  scale_size(range = c(1, 30)) +
  labs(x="Gini-Index", y="Happiness Score") +
  scale_y_continuous(limits = c(15, 85), 
                     breaks = seq(20,80, by=10),
                     labels = paste0(seq(20,80, by=10), "%")) +
  scale_x_continuous(limits = c(18,75),
                     breaks = seq(20,70, by= 5)) +
  scale_fill_manual(
    values = c(tuerkis, gruen, rot, gelb),
    breaks = c("africa", "americas", "asia", "europe")) +
  theme(text = element_text(size=12),
        axis.text = element_text(size=rel(.8)),
        axis.title = element_text(size=rel(1.2)),
        panel.grid.major = element_line(colour = "azure2")) +
  labs(title="Bubble Chart im Gapminder-Look",
       subtitle="Jahr: 2023",
       x="Gini-Index",
       y="Happiness Score (WHR)",
       fill="Weltregion",
       size="Einwohnerzahl\n(in Mio.)") +
  guides(fill = guide_legend(override.aes = list(size = 5), order=1)) 

p_bubble

Interaktive Grafik mit plotly

Wendet man nun ggplotly() darauf an, entsteht diese interaktive Grafik. Das mouse-over-Textfeld funktioniert bereits, ließe sich aber auch noch feiner anpassen (Stichwort: tooltip).

ggplotly(p_bubble) 

Interaktive Grafiken speichern

Die mit ggplotly erzeugten HTML-Objekte können mit der Funktion saveWidget() aus dem R-Paket htmlwidgets als HTML-Datei gespeichert werden.

p_plotly <- ggplotly(p_bubble) 
saveWidget(p_plotly, file = "bubbles.html")

Um die Größe und Proportionen der HTML-Grafik zu kontrollieren, kann man wie folgt vorgehen:

p_plotly <- ggplotly(p_bubble) %>%
  layout(width = 1200, height = 400)

saveWidget(p_plotly, file = "bubbles_wide.html")

Abbildung von Allison Horst